package com.example.lexiangbackend.service;

import com.example.lexiangbackend.entity.User;
import com.example.lexiangbackend.entity.Admin;
import com.example.lexiangbackend.repository.UserRepository;
import com.example.lexiangbackend.repository.AdminRepository;
import com.example.lexiangbackend.dto.*;
import com.example.lexiangbackend.util.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.regex.Pattern;

@Service
@Transactional
public class AuthService {

    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private AdminRepository adminRepository;

    // 密码编码器已移除，使用明文密码

    @Autowired
    private JwtUtil jwtUtil;

    // 存储验证码的临时Map（实际项目中应该使用Redis）
    private Map<String, String> verificationCodes = new HashMap<>();
    private Map<String, LocalDateTime> codeExpirationTimes = new HashMap<>();

    /**
     * 用户邮箱/用户名登录
     */
    public AuthResponse authenticateUser(LoginRequest request) {
        // 判断输入的是邮箱还是用户名
        boolean isEmail = isValidEmail(request.getEmailOrUsername());
        
        Optional<User> userOptional;
        if (isEmail) {
            userOptional = userRepository.findByEmail(request.getEmailOrUsername());
        } else {
            userOptional = userRepository.findByUsername(request.getEmailOrUsername());
        }

        if (userOptional.isEmpty()) {
            String fieldName = isEmail ? "邮箱" : "用户名";
            throw new RuntimeException("该" + fieldName + "未注册，请先注册账户");
        }

        User user = userOptional.get();
        
        // 验证密码（明文比较）
        if (!request.getPassword().equals(user.getPassword())) {
            throw new RuntimeException("密码错误");
        }

        // 检查用户状态
        if (user.getStatus() != null && user.getStatus() != 0) {
            throw new RuntimeException("账户已被禁用，请联系管理员");
        }

        // 更新最后登录时间
        user.setLastLoginTime(LocalDateTime.now());
        userRepository.save(user);

        // 生成Token
        long expirationTime = request.isRememberMe() ? 
            7 * 24 * 60 * 60 * 1000L : // 7天
            24 * 60 * 60 * 1000L; // 1天
        
        String token = jwtUtil.generateToken(user.getUsername(), "USER", expirationTime);

        return new AuthResponse(true, "登录成功", token, "USER", user);
    }

    /**
     * 用户手机号登录
     */
    public AuthResponse authenticateUserByPhone(PhoneLoginRequest request) {
        // 验证验证码
        if (!verifyCode(request.getPhone(), request.getVerificationCode())) {
            throw new RuntimeException("验证码错误或已过期");
        }

        // 查找用户
        Optional<User> userOptional = userRepository.findByPhone(request.getPhone());
        if (userOptional.isEmpty()) {
            throw new RuntimeException("该手机号未注册，请先注册账户");
        }

        User user = userOptional.get();
        
        // 检查用户状态
        if (user.getStatus() != null && user.getStatus() != 0) {
            throw new RuntimeException("账户已被禁用，请联系管理员");
        }

        // 更新最后登录时间
        user.setLastLoginTime(LocalDateTime.now());
        userRepository.save(user);

        // 清除验证码
        verificationCodes.remove(request.getPhone());
        codeExpirationTimes.remove(request.getPhone());

        // 生成Token
        long expirationTime = request.isRememberMe() ? 
            7 * 24 * 60 * 60 * 1000L : // 7天
            24 * 60 * 60 * 1000L; // 1天
        
        String token = jwtUtil.generateToken(user.getUsername(), "USER", expirationTime);

        return new AuthResponse(true, "登录成功", token, "USER", user);
    }

    /**
     * 用户注册
     */
    public AuthResponse registerUser(RegisterRequest request) {
        // 检查邮箱是否已存在
        if (userRepository.findByEmail(request.getEmail()).isPresent()) {
            throw new RuntimeException("该邮箱已被注册");
        }

        // 检查用户名是否已存在
        if (userRepository.findByUsername(request.getUsername()).isPresent()) {
            throw new RuntimeException("该用户名已被使用");
        }

        // 验证必需的同意条款
        if (!request.getAcceptTerms() || !request.getAcceptPrivacy()) {
            throw new RuntimeException("必须同意使用条款和隐私政策");
        }

        // 创建用户
        User user = new User();
        user.setEmail(request.getEmail());
        user.setUsername(request.getUsername());
        user.setPassword(request.getPassword());
        user.setStatus(0); // 正常状态
        user.setCreatedTime(LocalDateTime.now());
        
        // 设置默认值避免数据库字段错误
        user.setAcceptMarketing(false);
        user.setShareData(false);

        // 保存用户
        userRepository.save(user);

        return new AuthResponse(true, "注册成功", null, null, null);
    }

    /**
     * 管理员登录
     */
    public AuthResponse authenticateAdmin(AdminLoginRequest request) {
        // 查找管理员用户
        Optional<Admin> adminOptional = adminRepository.findByUsername(request.getUsername());
        if (adminOptional.isEmpty()) {
            throw new RuntimeException("管理员用户不存在");
        }

        Admin admin = adminOptional.get();

        // 验证密码（明文比较）
        if (!request.getPassword().equals(admin.getPassword())) {
            throw new RuntimeException("管理员密码错误");
        }

        // 检查管理员状态
        if (!admin.isActive()) {
            throw new RuntimeException("管理员账户已被禁用");
        }

        // 生成Token
        long expirationTime = request.isRememberMe() ? 
            7 * 24 * 60 * 60 * 1000L : // 7天
            8 * 60 * 60 * 1000L; // 8小时
        
        String token = jwtUtil.generateToken(admin.getUsername(), "ADMIN", expirationTime);

        // 创建一个临时User对象用于返回（保持接口一致性）
        User adminAsUser = new User();
        adminAsUser.setUsername(admin.getUsername());
        // 注意：不设置敏感信息如密码

        return new AuthResponse(true, "管理员登录成功", token, "ADMIN", adminAsUser);
    }

    /**
     * 发送验证码
     */
    public AuthResponse sendVerificationCode(String phone) {
        // 验证手机号格式
        if (!isValidPhone(phone)) {
            throw new RuntimeException("手机号格式不正确");
        }

        // 生成4位随机验证码
        String code = String.format("%04d", new Random().nextInt(10000));
        
        // 设置过期时间（5分钟）
        LocalDateTime expirationTime = LocalDateTime.now().plusMinutes(5);
        
        // 存储验证码
        verificationCodes.put(phone, code);
        codeExpirationTimes.put(phone, expirationTime);

        // TODO: 这里应该调用短信服务发送验证码
        // smsService.sendCode(phone, code);
        
        // 临时：在控制台打印验证码（仅用于开发测试）
        System.out.println("验证码已发送到 " + phone + ": " + code);

        // 开发环境返回验证码（生产环境应该移除）
        return new AuthResponse(true, "验证码已发送", null, null, null, code);
    }

    /**
     * 绑定手机号
     */
    public AuthResponse bindPhone(String token, BindPhoneRequest request) {
        // 验证Token并获取用户
        User user = verifyToken(token);
        
        // 验证验证码
        if (!verifyCode(request.getPhone(), request.getVerificationCode())) {
            throw new RuntimeException("验证码错误或已过期");
        }
        
        // 检查手机号是否已被其他用户绑定
        Optional<User> existingUser = userRepository.findByPhone(request.getPhone());
        if (existingUser.isPresent() && !existingUser.get().getUserId().equals(user.getUserId())) {
            throw new RuntimeException("该手机号已被其他账户绑定");
        }
        
        // 更新用户的手机号
        user.setPhone(request.getPhone());
        userRepository.save(user);
        
        // 清除验证码
        verificationCodes.remove(request.getPhone());
        codeExpirationTimes.remove(request.getPhone());
        
        return new AuthResponse(true, "手机号绑定成功", null, null, user);
    }

    /**
     * 更新个人资料
     */
    public AuthResponse updateProfile(String token, UpdateProfileRequest request) {
        // 验证Token并获取用户
        User user = verifyToken(token);
        
        // 验证验证码
        String userPhone = user.getPhone();
        if (userPhone == null || userPhone.isEmpty()) {
            throw new RuntimeException("用户尚未绑定手机号");
        }
        
        if (!verifyCode(userPhone, request.getVerificationCode())) {
            throw new RuntimeException("验证码错误或已过期");
        }
        
        // 检查用户名是否已被其他用户使用
        if (!user.getUsername().equals(request.getUsername())) {
            Optional<User> existingUser = userRepository.findByUsername(request.getUsername());
            if (existingUser.isPresent()) {
                throw new RuntimeException("该用户名已被使用");
            }
        }
        
        // 检查邮箱是否已被其他用户使用
        if (!user.getEmail().equals(request.getEmail())) {
            Optional<User> existingUser = userRepository.findByEmail(request.getEmail());
            if (existingUser.isPresent()) {
                throw new RuntimeException("该邮箱已被注册");
            }
        }
        
        // 更新用户信息
        user.setUsername(request.getUsername());
        user.setEmail(request.getEmail());
        userRepository.save(user);
        
        // 清除验证码
        verificationCodes.remove(userPhone);
        codeExpirationTimes.remove(userPhone);
        
        return new AuthResponse(true, "个人资料更新成功", null, null, user);
    }

    /**
     * 修改密码
     */
    public AuthResponse changePassword(String token, ChangePasswordRequest request) {
        // 验证Token并获取用户
        User user = verifyToken(token);
        
        // 验证验证码
        String userPhone = user.getPhone();
        if (userPhone == null || userPhone.isEmpty()) {
            throw new RuntimeException("用户尚未绑定手机号");
        }
        
        if (!verifyCode(userPhone, request.getVerificationCode())) {
            throw new RuntimeException("验证码错误或已过期");
        }
        
        // 验证新密码和确认密码是否一致
        if (!request.getNewPassword().equals(request.getConfirmPassword())) {
            throw new RuntimeException("两次输入的密码不一致");
        }
        
        // 检查新密码与当前密码是否相同
        if (user.getPassword().equals(request.getNewPassword())) {
            throw new RuntimeException("新密码不能与当前密码相同");
        }
        
        // 更新密码
        user.setPassword(request.getNewPassword());
        userRepository.save(user);
        
        // 清除验证码
        verificationCodes.remove(userPhone);
        codeExpirationTimes.remove(userPhone);
        
        return new AuthResponse(true, "密码修改成功", null, null, user);
    }

    /**
     * 注销账户
     */
    public AuthResponse deleteAccount(String token, DeleteAccountRequest request) {
        // 验证Token并获取用户
        User user = verifyToken(token);
        
        // 验证验证码
        String userPhone = user.getPhone();
        if (userPhone == null || userPhone.isEmpty()) {
            throw new RuntimeException("用户尚未绑定手机号");
        }
        
        if (!verifyCode(userPhone, request.getVerificationCode())) {
            throw new RuntimeException("验证码错误或已过期");
        }
        
        // 验证密码
        if (!request.getPassword().equals(user.getPassword())) {
            throw new RuntimeException("密码错误");
        }
        
        // 删除用户账户
        userRepository.delete(user);
        
        // 清除验证码
        verificationCodes.remove(userPhone);
        codeExpirationTimes.remove(userPhone);
        
        return new AuthResponse(true, "账户注销成功", null, null, null);
    }

    /**
     * 从Token中提取角色信息
     */
    public String extractRoleFromToken(String token) {
        try {
            return jwtUtil.extractRole(token);
        } catch (Exception e) {
            throw new RuntimeException("无法提取Token角色信息");
        }
    }

    /**
     * 验证Token
     */
    public User verifyToken(String token) {
        try {
            System.out.println("开始验证Token: " + token.substring(0, Math.min(20, token.length())) + "...");
            
            String username = jwtUtil.extractUsername(token);
            System.out.println("从Token中提取的用户名: " + username);
            
            if (username != null && jwtUtil.validateToken(token, username)) {
                System.out.println("Token验证成功，开始查询用户");
                
                Optional<User> userOptional = userRepository.findByUsername(username);
                System.out.println("数据库查询结果: " + (userOptional.isPresent() ? "找到用户" : "未找到用户"));
                
                if (userOptional.isPresent()) {
                    User user = userOptional.get();
                    System.out.println("用户对象详情: ");
                    System.out.println("  - 用户ID: " + user.getUserId());
                    System.out.println("  - 用户名: " + user.getUsername());
                    System.out.println("  - 邮箱: " + user.getEmail());
                    System.out.println("  - 状态: " + user.getStatus());
                    System.out.println("  - 创建时间: " + user.getCreatedTime());
                    
                    // 检查用户ID是否为空
                    if (user.getUserId() == null) {
                        System.err.println("严重错误：用户对象的ID为null！这表示数据库中的user_id字段为null");
                        System.err.println("用户名: " + user.getUsername());
                        System.err.println("这可能是数据库表结构问题或数据完整性问题");
                        throw new RuntimeException("用户ID为空，数据异常");
                    }
                    
                    return user;
                } else {
                    System.err.println("根据用户名未找到用户: " + username);
                }
            } else {
                System.err.println("Token验证失败，用户名: " + username);
            }
        } catch (Exception e) {
            System.err.println("Token验证异常: " + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    // 私有辅助方法
    private boolean isValidEmail(String email) {
        String emailRegex = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$";
        return Pattern.matches(emailRegex, email);
    }

    private boolean isValidPhone(String phone) {
        String phoneRegex = "^1[3-9]\\d{9}$";
        return Pattern.matches(phoneRegex, phone);
    }

    private boolean verifyCode(String phone, String code) {
        String storedCode = verificationCodes.get(phone);
        LocalDateTime expirationTime = codeExpirationTimes.get(phone);
        
        if (storedCode == null || expirationTime == null) {
            return false;
        }
        
        if (LocalDateTime.now().isAfter(expirationTime)) {
            // 验证码已过期，清除
            verificationCodes.remove(phone);
            codeExpirationTimes.remove(phone);
            return false;
        }
        
        return storedCode.equals(code);
    }
} 